package com.hmall.gateway.routers;

import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.annotation.NacosProperties;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import io.github.classgraph.json.JSONUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import springfox.documentation.spring.web.json.Json;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;

/**
 * @author 宛远鸿
 * @version 1.0
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class DynamicRouteLoader {
    private final NacosConfigManager nacosConfigManager;
    private final RouteDefinitionWriter writer;
    private final String dataId="gateway-routes.json";
    private final String group="DEFAULT_GROUP";
    private final Set<String> routeIds=new HashSet<>();

    @PostConstruct
    public void initRouteConfingListener() throws NacosException {
        //项目启动时，先拉取一次配置，并且添加配置
        String configInfo = nacosConfigManager.getConfigService()
                .getConfigAndSignListener(dataId, group, 5000, new Listener() {
                    @Override
                    public Executor getExecutor() {
                        return null;
                    }

                    @Override
                    public void receiveConfigInfo(String configInfo) {
                    //2.监听到配置变更，需要去更新路由表
                        try {
                            updateConfigInfo(configInfo);
                        } catch (NacosException e) {
                            throw new RuntimeException(e);
                        }
                    }
                });
        //3.第一次读取到配置,也需要更新到路由表
        updateConfigInfo(configInfo);
    }
    public void updateConfigInfo(String confingInfo) throws NacosException {
       log.debug("监听到路由配置信息：{}",confingInfo);
        // 1.解析配置文件,转为RouteDefinition
        List<RouteDefinition> routeDefinitions = JSONUtil.toList(confingInfo, RouteDefinition.class);
        //2.删除旧路由表
        for (String routeId : routeIds) {
            writer.delete(Mono.just(routeId)).subscribe();
        }
        routeIds.clear();

            //3.更新路由表
        for (RouteDefinition routeDefinition : routeDefinitions) {
            //3.1更新路由表
         writer.save(Mono.just(routeDefinition)).subscribe();
            //3.2记录路由id,便于下一次更新时删除
            routeIds.add(routeDefinition.getId());
        }

    }

}
